package com.letoken.platform.repo.helper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.letoken.platform.pub.constant.ConstantsValue;
import com.letoken.platform.pub.constant.RedisKeyConstant;
import com.letoken.platform.pub.enums.TokenTransactionTypeEnum;
import com.letoken.platform.pub.util.LocalDateTool;
import com.letoken.platform.pub.util.LocalEnvUtils;
import com.letoken.platform.repo.app.dao.AppConsumerWeightingMapper;
import com.letoken.platform.repo.app.dao.AppUserAssetsHistoryMapper;
import com.letoken.platform.repo.app.dao.AppUserMapper;
import com.letoken.platform.repo.app.dao.AppUserTeamMapper;
import com.letoken.platform.repo.app.po.AppConsumerWeighting;
import com.letoken.platform.repo.app.po.AppUserTeam;
import com.letoken.platform.repo.mall.dao.AppMallAmbSummaryMapper;
import com.letoken.platform.repo.utlis.lock.Lock;
import com.letoken.platform.repo.utlis.lock.LockCategoryEnum;
import lombok.Data;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.letoken.platform.pub.constant.RedisKeyConstant.APP_CONSUMER_DATE_MARK;

@Component
public class CalculateConsumerValue {


    private static ExecutorService oneThread = Executors.newSingleThreadExecutor();

    @Autowired
    AppUserTeamMapper appUserTeamMapper;
    @Autowired
    AppUserAssetsHistoryMapper appUserAssetsHistoryMapper;
    @Autowired
    AppMallAmbSummaryMapper appMallAmbSummaryMapper;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    AppConsumerWeightingMapper appConsumerWeightingMapper;
    @Autowired
    AppUserMapper appUserMapper;


    @Data
    public static class TransferPo{
        private String userId ;
        private String weighting;
        TransferPo(String userId,String weighting){
            this.userId = userId;
            this.weighting = weighting;
        }
    }

    @Data
    public static class ObtainAssetPo{
        private Integer userId ;
        private BigDecimal amount;
    }

    @Data
    public static class ConsumerValuePo{
        private Integer id = Integer.MAX_VALUE;
    }



    public static String getInitDate(){
//        if (LocalEnvUtils.isProd()){
//
//        }
//        return "2023-11-03";
        return "2023-11-10";
    }




    // 针对推广分红和基金加权计算的锁
    @Lock(ce = LockCategoryEnum.ID,value = "GROUB:CONSUMER_VALUE:",field = "id",expire = 15l)
    public void calculateConsumerMark(ConsumerValuePo po){
        // 上线七天之后允许运行
        if (start()){
            return;
        }


//        final LocalDateTime currentTime = LocalDateTime.now();
//        String now = LocalDateTool.getDefaultTime(LocalDateTool.yyyyMMdd);
//
//
//        final String dateKey = APP_CONSUMER_DATE_MARK;
//        if (redisTemplate.hasKey(dateKey)){
//            String oldDate = redisTemplate.opsForValue().get(dateKey);
//            if (ObjectUtils.isNotEmpty(oldDate)){
//                // 需要重新判定
//                if (LocalDateTool.getDiffByDate(oldDate,now) >= ConstantsValue.CONSUME_DETERMINE_CYCLE ){
//                    redisTemplate.delete(getKey());
//                    redisTemplate.delete(dateKey);
//                }
//            }
//        }
//
//        if (redisTemplate.hasKey(getKey())){
//            return;
//        }
//
//        // 所有的基金分红
//        List<ObtainAssetPo> assetPos = appUserAssetsHistoryMapper.obtainAssetAmount(getInitDate());
//        // 所有全球推广分红
//        List<ObtainAssetPo> ambPos = appMallAmbSummaryMapper.obtainAssetAmount(getInitDate());
//        assetPos.addAll(ambPos);
//        // 用户ID<->累计加权分红
//        ConcurrentMap<Integer,BigDecimal> m = assetPos.parallelStream().filter(x-> (ObjectUtils.isNotEmpty(x.getUserId()) && ObjectUtils.isNotEmpty(x.getAmount())) && x.getAmount().compareTo(BigDecimal.ZERO) > 0 )
//                .collect(Collectors.toConcurrentMap(ObtainAssetPo::getUserId, ObtainAssetPo::getAmount,(v1, v2) -> v1.add(v2)));
//        if (CollectionUtil.isNotEmpty(m)){
//            LambdaQueryWrapper<AppUserTeam> lqwAma = new LambdaQueryWrapper<>();
//            lqwAma.in(AppUserTeam::getUserId,m.keySet()).select(AppUserTeam::getUserId, AppUserTeam::getConsumerValue);
//            // 用户ID<->消费建设值
//            ConcurrentMap<Integer,BigDecimal> a  = appUserTeamMapper.selectList(lqwAma).parallelStream().collect(Collectors.toConcurrentMap(AppUserTeam::getUserId,AppUserTeam::getConsumerValue));
//
//            // 判定达标的用户
//            Map<String,String> conditionResult = m.keySet().stream().filter(x -> ObjectUtils.isNotEmpty(a.get(x)) && a.get(x).compareTo(m.get(x).multiply(ConstantsValue.CONSUME_THRESHOLD)) >= 0)
//                    .map(y -> new TransferPo(String.valueOf(y),String.format("%s-%s",m.get(y),a.get(y))))
//                    .collect(Collectors.toMap(TransferPo::getUserId, TransferPo::getWeighting));
//
//            // 所有累计加权分红大于0的用户
//            Map<String,String> result = m.keySet().stream().map(y -> new TransferPo(String.valueOf(y),String.format("%s-%s",m.get(y),a.get(y))))
//                    .collect(Collectors.toMap(TransferPo::getUserId, TransferPo::getWeighting));
//            if (CollectionUtil.isNotEmpty(conditionResult))
//                redisTemplate.opsForHash().putAll(getKey(),conditionResult);
//            else
//                conditionResult = new HashMap<>();
//
//            oneThread.submit(new WeightingTask(result,conditionResult,currentTime,appConsumerWeightingMapper));
//
//            redisTemplate.opsForValue().set(dateKey,now);
//
//        }
    }



    public BigDecimal weightedDividends(Integer userId){
        BigDecimal a = appMallAmbSummaryMapper.obtainAssetAmountUser(userId,CalculateConsumerValue.getInitDate());
        BigDecimal b = appUserAssetsHistoryMapper.obtainAssetAmountUser(userId,CalculateConsumerValue.getInitDate());
        if (ObjectUtil.isEmpty(a)) a = BigDecimal.ZERO;
        if (ObjectUtil.isEmpty(b)) b = BigDecimal.ZERO;
        return a.add(b);

    }

//    public static void main(String[] args) {
//        long t = 2l;
//        Integer f = Integer.valueOf(7);
//        if (t < f ){
//            System.out.println("比对正确");
//        }
//    }

    // true 表示该逻辑还未开始生效
    public Boolean start(){
        final String initDate = getInitDate();
        if (LocalDateTool.getDiffByDate(initDate,LocalDateTool.getDefaultTime(LocalDateTool.yyyyMMdd)) < ConstantsValue.CONSUME_DETERMINE_CYCLE){
            return true;
        }
        return false;
    }


    public String getKey(){
        return RedisKeyConstant.APP_CONSUMER_MARK;
    }




    public boolean hasKey(String hashName,String key){
        // 开始时间之前，不拦截用户获取收益
        // 周期内新增用户，不拦截用户获取收益
//        if (start()){
//            return true;
//        }
//        return redisTemplate.opsForHash().hasKey(hashName,key);
        return true;
    }


    public boolean isNewUser(Integer userId ){
        final String dateKey = APP_CONSUMER_DATE_MARK;
        // 判定逻辑已经生效了
        if (redisTemplate.hasKey(dateKey)){
            String date = redisTemplate.opsForValue().get(dateKey);
            LocalDateTime localDateTime = appUserMapper.getRegisterTime(userId);
            if (LocalDateTool.getDiffByDate(date,localDateTime.format(LocalDateTool.yyyyMMdd)) >= 0){
                return true;
            }

        }
        return false;

    }

    public static void main(String[] args) {
        String a = "2023-11-10";
        String b = "2023-11-10";
        System.out.println(LocalDateTool.getDiffByDate(a, b));
    }




    private static class WeightingTask implements Runnable{

        private Map<String,String> map;
        private LocalDateTime now;
        private AppConsumerWeightingMapper appConsumerWeightingMapper;
        private Map<String,String> conditionResult;

        WeightingTask(Map<String,String> map,Map<String,String> conditionResult, LocalDateTime now,AppConsumerWeightingMapper mapper){
            this.map = map;
            this.now = now;
            this.appConsumerWeightingMapper = mapper;
            this.conditionResult = conditionResult;
        }

        @Override
        public void run() {
            List<AppConsumerWeighting> list = new ArrayList<>();
            map.keySet().stream().forEach(x->{

                AppConsumerWeighting appConsumerWeighting = new AppConsumerWeighting();
                appConsumerWeighting.setUserId(Integer.valueOf(x));
                String v = map.get(x);
                String[] arr = v.split("-");
                BigDecimal weighting = new BigDecimal(arr[0]);
                BigDecimal consumerValue = new BigDecimal(arr[1]);
                appConsumerWeighting.setWeighting(weighting);
                appConsumerWeighting.setConsumerValue(consumerValue);
                appConsumerWeighting.setCreateTime(now);
                if (conditionResult.containsKey(x)){
                    appConsumerWeighting.setStatus(ConstantsValue.I_1);
                }else {
                    appConsumerWeighting.setStatus(ConstantsValue.I_0);
                }
                list.add(appConsumerWeighting);

            });

            if (CollectionUtil.isNotEmpty(list)){
                List<List<AppConsumerWeighting>> allRecords = Lists.partition(list,400);
                allRecords.forEach(x->{
                    appConsumerWeightingMapper.insertBatchSomeColumn(x);
                });
            }
        }
    }


}
